package com.skyinno.mrms.utils;

import org.apache.log4j.Logger;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.Map.Entry;
import java.util.zip.ZipFile;

/**
 * 
 */
public class Utils {
    private static final Logger logger = Logger.getLogger(Utils.class);

    public static final String DATEFORMAT_NYR = "yyyy-MM-dd";
    public static final String DATEFORMAT_NYR_EMP = "yyyyMMdd";
    public static final String DATEFORMAT_NYRSFM = "yyyy-MM-dd HH:mm:ss";
    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     * added by xulei 2016.9.9.
     */
    public static int daysBetween(Date smdate, Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24)+1;

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     *字符串的日期格式的计算
     * added by xulei 2016.9.9.
     */
    public static int daysBetween(String smdate,String bdate) throws ParseException{
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(smdate));
        long time1 = cal.getTimeInMillis();
        cal.setTime(sdf.parse(bdate));
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24)+1;

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 格式化日期，返回字符串形式，形如"yyyy-MM-dd"
     *
     * @param date
     * @return
     * added by xulei 2016.9.9.
     */
    public static String formatDate(Object date) {
        if(date==null){
          return null;
        }
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        return dateFormat.format(date);
    }

    /**
     * 字符合并
     * added by xulei 2016.12.27
     */
    public static String append(Object... arr){
        StringBuilder sb = new StringBuilder();
        for(Object obj : arr){
            sb.append(obj);
        }
        return sb.toString();
    }

    /**
     * 将List元素拼装成逗号分隔的字符串
     * added by xulei 2016.12.27
     */
    public static String list2String(List<String> arr){
        StringBuilder sb = new StringBuilder();
        for(Object obj : arr){
            sb.append(obj).append(",");
        }
        return sb.deleteCharAt(sb.length() - 1).toString();
    }

    /**
     * 获取对象的字节个数.
     *
     * @param obj
     * @return
     *
     * @author xulei
     * @date 2013-6-25 上午11:26:17
     */
    public static int getUtf8BytesLength(Object obj){
        try{
            if(obj instanceof String){
                return ((String)obj).getBytes("UTF-8").length;
            }

            return String.valueOf(obj).getBytes("UTF-8").length;
        }catch(Exception e){
            if(obj instanceof String){
                return ((String)obj).getBytes().length;
            }

            return String.valueOf(obj).getBytes().length;
        }

    }

    /**
     * 按UTF-8编码的字符串，截取指定长度的字符串
     *
     * @param src
     *            按UTF-8编码的字符串
     * @param count
     *            指定长度
     * @return 返回截取的字符串
     *
     * @author xulei
     * @date 2013-7-16 上午10:06:21
     */
    public static String subUTF8String(String src, int count){
        if(src == null || src.length() <= 0){
            return src;
        }

        int len = getUtf8BytesLength(src);
        if(len <= count){
            return src;
        }

        StringBuffer buff = new StringBuffer();
        char c;
        int idx = 0;
        int cLen = 0;
        for(int pos = count; pos > 0;){
            c = src.charAt(idx);
            cLen = getUtf8BytesLength(c);
            pos = pos - cLen;
            if(pos >= 0){
                buff.append(c);
                idx++;
            }
        }

        return buff.toString();
    }

    /**
     * 判断double类型数字是否为0
     *
     * @param d
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isDoubleZero(Double d){
        BigDecimal zero = new BigDecimal(0.0D);
        BigDecimal src = new BigDecimal(d);
        return src.compareTo(zero) == 0;
    }

    /**
     * 格式化双精度的数字
     *
     * @param position
     * @param formatStr
     * @return Added by xulei 2013.03.14
     */
    public static String formatPosition(double position, String formatStr){
        DecimalFormat df = new DecimalFormat(formatStr);
        return df.format(position);
    }

    /**
     * 判断对象值是否为空： 若对象为字符串，判断对象值是否为null或空格; 若对象为数组，判断对象值是否为null，或数组个数是否为0; 若对象为List。判断对象值是否为null，或List元素是否个数为0;
     * 其他类型对象，只判断值是否为null.
     *
     * @param value
     * @return true
     * added by xulei 2016.12.27
     */
    public static boolean isEmpty(Object value){
        if(value == null){
            return true;
        }else if((value instanceof String) && ((((String)value).trim().length() < 1)||((String)value).equals(""))){
            return true;
        }else if(value.getClass().isArray()){
            if(0 == java.lang.reflect.Array.getLength(value)){
                return true;
            }
        }else if(value instanceof List){
            if(((List<?>)value).isEmpty()){
                return true;
            }
        }else if(value instanceof Map){
            if(((Map<?, ?>)value).isEmpty()){
                return true;
            }
        }else if(value instanceof Set){
            if(((Set<?>)value).isEmpty()){
                return true;
            }
        }
        return false;
    }

    public static boolean isNotEmpty(Object value){
        return !isEmpty(value);
    }

    /**
     * 将中文字符转换成utf-8格式
     *
     * @param xmlStr
     * @return Added by xulei 2012.02.15
     */
    public static String encodeUTF8(String xmlStr){
        String str = "";
        try{
            str = URLEncoder.encode(xmlStr, "utf-8");
        }catch(UnsupportedEncodingException e){
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        return str;
    }

    /**
     * added by xulei 2016.12.27
     * @param map
     * @return
     */
    public static Map<String, Object> convertMap(Map<String, Integer> map){
        Map<String, Object> target = new HashMap<String, Object>(map.size());
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        for(Map.Entry<String, Integer> e : set){
            target.put(e.getKey(), e.getValue());
        }

        return target;
    }

    /**
     * 将utf-8格式字符转换成中文字符
     *
     * @param str
     * @return Added by xulei 2012.02.15
     */
    public static String decodeUTF8(String str){
        String xmlStr = "";
        try{
            xmlStr = URLDecoder.decode(str, "utf-8");
        }catch(UnsupportedEncodingException e){
            e.printStackTrace();
        }catch(Exception e){
            e.printStackTrace();
        }
        return xmlStr;
    }

    /**
     * 1.全角：指一个字符占用两个标准字符位置。汉字字符和规定了全角的英文字符及国标GB2312-80中的图形符号和特殊字符都是全角字符。 一般的系统命令是不用全角字符的，只是在作文字处理时才会使用全角字符。
     * 2.半角：指一字符占用一个标准的字符位置。通常的英文字母、数字键、符号键都是半角的 ，半角的显示内码都是一个字节。在系统内部，以上三种字符是作为基本代码处理的，所以用户输入命令和参数时一般都使用半角。
     * 3.全角与半角在计算机中的表示：据我所知，全角的第一个字节是163（我用-93），然后第二个字节与半角相差128。全角空格和半角空格也要考虑进去。
     *
     *
     * 半角转全角
     *
     * @param input
     *            String.
     * @return 全角字符串. Added by xulei 2011.06.08
     */
    public static String ToSBC(String input){
        char c[] = input.toCharArray();
        for(int i = 0; i < c.length; i++){
            if(c[i] == ' '){
                c[i] = '\u3000'; // 采用十六进制,相当于十进制的12288

            }else if(c[i] < '\177'){ // 采用八进制,相当于十进制的127
                c[i] = (char)(c[i] + 65248);

            }
        }
        return new String(c);
    }

    /**
     * 全角转半角
     *
     * @param input
     *            String.
     * @return 半角字符串 Added by xulei 2011.06.08
     */
    public static String ToDBC(String input){

        char c[] = input.toCharArray();
        for(int i = 0; i < c.length; i++){
            if(c[i] == '\u3000'){
                c[i] = ' ';
            }else if(c[i] > '\uFF00' && c[i] < '\uFF5F'){
                c[i] = (char)(c[i] - 65248);

            }
        }
        String returnString = new String(c);

        return returnString;
    }

    /**
     * Object转换为float，失败返回0
     *
     * @param o
     * @return
     * added by xulei 2016.12.27
     */
    public static float toFloat(Object o){
        try{
            return Float.parseFloat(String.valueOf(o));
        }catch(Exception e){
            return 0;
        }
    }

    /**
     * Object转换为double，失败返回0
     *
     * @param o
     * @return
     * added by xulei 2016.12.27
     */
    public static double toDouble(Object o){
        try{
            return Double.parseDouble(String.valueOf(o));
        }catch(Exception e){
            return 0;
        }
    }

    /**
     * Object转换为整形，失败返回0
     *
     * @param o
     * @return
     * added by xulei 2016.12.27
     */
    public static int toInteger(Object o){
        return toInteger(o, 0);
    }

    /**
     * Object转换为整形
     *
     * @param o
     * @param def
     *            转换失败默认值
     * @return
     * added by xulei 2016.12.27
     */
    public static int toInteger(Object o, int def){
        try{
            if (o == null){
                return def;
            }

            String typeName = o.getClass().getName();
            if ("int".equals(typeName) || Integer.class.getName().equals(typeName)){
                return (Integer)o;
            }

            if (BigDecimal.class.getName().equals(typeName)){
                return ((BigDecimal)o).intValue();
            }

            return new BigDecimal(o.toString()).intValue();
        }catch(Exception e){
            return def;
        }
    }

    /**
     * Object转换为长整形，失败返回0
     *
     * @param o
     * @return
     * added by xulei 2016.12.27
     */
    public static long toLong(Object o){
        return toLong(o, 0L);
    }

    public static long toLong(Object o, Long defaultValue){
        try{
            if (o == null){
                return defaultValue;
            }

            String typeName = o.getClass().getName();
            if ("long".equals(typeName) || Long.class.getName().equals(typeName)){
                return (Long)o;
            }

            if (BigDecimal.class.getName().equals(typeName)){
                return ((BigDecimal)o).longValue();
            }

            return new BigDecimal(o.toString()).longValue();
        }catch(Exception e){
            return 0L;
        }
    }


    /**
     * Object转换为短整形，失败返回0
     *
     * @param o
     * @return
     * added by xulei 2016.12.27
     */
    public static Short toShort(Object o){
        try{
            if (o == null){
                return 0;
            }

            String typeName = o.getClass().getName();
            if ("short".equals(typeName) || Short.class.getName().equals(typeName)){
                return (Short)o;
            }

            if (BigDecimal.class.getName().equals(typeName)){
                return ((BigDecimal)o).shortValue();
            }

            return new BigDecimal(o.toString()).shortValue();
        }catch(Exception e){
            return 0;
        }
    }

    /**
     * 判断两个字符串值是否相同，不区分大小写
     *
     * @param str1
     * @param str2
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isStrsEqual(String str1, String str2){
        if(isEmpty(str1) && isEmpty(str2)){
            return true;
        }

        if(!isEmpty(str1) && !isEmpty(str2)){
            return str1.equalsIgnoreCase(str2);
        }

        return false;
    }

    /**
     * 根据元素的自然顺序对指定Set中的元素按升序进行排序。Set中的所有元素都必须实现 Comparable 接口。 此外，列表中的所有元素都必须是可相互比较的（也就是说，对于列表中的任何 e1 和 e2
     * 元素，e1.compareTo(e2) 不得抛出 ClassCastException）。 此排序方法具有稳定性：不会因调用 sort 方法而对相等的元素进行重新排序。
     * 由于参数Set可能是不可更改的，因此将Set里的元素排序后，存放到List中，并将该List作为方法的返回值。
     *
     * @param set
     *            要排序的Set
     * @return 排序后的元素列表
     * added by xulei 2016.12.27
     */
    public static <T extends Comparable<? super T>> List<T> sort(Set<T> set){
        Object[] a = set.toArray();
        Arrays.sort(a);
        List<T> list = new ArrayList<T>(set.size());
        for(int j = 0; j < a.length; j++){
            list.add((T)a[j]);
        }

        return list;
    }

    /**
     * 身份证号码自动转换，15位转成18位，18位转成15位
     *
     * @param idNum
     * @return
     * added by xulei 2016.12.27
     */
    public static String convertIdNum18or15(String idNum){
        if(idNum != null && idNum.length() == 15){
            String[] strJiaoYang = {
                    "1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2", "1"
            };
            int[] intQuan = {
                    7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2, 1
            };
            int intTemp = 0;
            String tempidNum = idNum.substring(0, 6) + "19" + idNum.substring(6);
            for(int i = 0; i < tempidNum.length(); i++){
                intTemp = intTemp + Integer.parseInt(tempidNum.substring(i, i + 1)) * intQuan[i];
            }
            intTemp = intTemp % 11;
            idNum = tempidNum + strJiaoYang[intTemp];
        }else if(idNum != null && idNum.length() == 18){
            idNum = idNum.substring(0, 17);
            idNum = idNum.substring(0, 6) + idNum.substring(8);
        }

        return idNum;
    }

    /**
     * 对日期进行转换
     *
     * @param dateStr
     *            Added by xulei 2010.12.31
     * @return
     * @throws ParseException
     * @throws Exception
     */
    public static String dateFormatNew(String dateStr) throws ParseException{
        if(dateStr == null || dateStr.length() <= 0){
            return "";
        }
        String srcFormat = "";
        String targetFormat = "";
        dateStr = dateStr.trim();
        if(dateStr.length() == 14){
            srcFormat = "yyyyMMddHHmmss";
            targetFormat = "yyyy年MM月dd日HH时mm分ss秒";
        }else if(dateStr.length() == 12){
            srcFormat = "yyyyMMddHHmm";
            targetFormat = "yyyy年MM月dd日HH时mm分";
        }else if(dateStr.length() == 10){
            srcFormat = "yyyyMMddHH";
            targetFormat = "yyyy年MM月dd日HH时";
        }else if(dateStr.length() == 8){
            srcFormat = "yyyyMMdd";
            targetFormat = "yyyy年MM月dd日";
        }else if(dateStr.length() == 6){
            srcFormat = "yyyyMM";
            targetFormat = "yyyy年MM月";
        }else if(dateStr.length() == 4){
            srcFormat = "yyyy";
            targetFormat = "yyyy年";
        }else{
            return "数据库该日期数据格式错误.";
        }

        SimpleDateFormat sdf = new SimpleDateFormat(srcFormat);
        SimpleDateFormat sdf2 = new SimpleDateFormat(targetFormat);
        Date date = sdf.parse(dateStr);
        return sdf2.format(date);
    }

    /**
     * 将DATE类型数据转换成指定格式的字符串数据
     *
     * @param srcDate
     * @param srcFormat
     * @return Added by xulei 2011.11.10
     */
    public static String dateToString(Date srcDate, String srcFormat){
        DateFormat df = new SimpleDateFormat(srcFormat);
        return df.format(srcDate);
    }

    /**
     * 将String类型数据转换成指定格式的date数据
     *
     * @param dateStr
     * @param srcFormat
     * @return Added by xulei 2011.11.16
     * @throws ParseException
     */
    public static Date stringToDate(String dateStr, String srcFormat) throws ParseException{
        DateFormat df = new SimpleDateFormat(srcFormat);
        return df.parse(dateStr);
    }

    static int[] DAYS = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    /**
     * @param date yyyyMMdd
     * @return
     * added by xulei 2017.01.13
     */
    public static boolean isValidDate(String date) {
        if (isEmpty(date)) return false;
        if (date.length() != 8) return false;
        try {
            int year = Integer.parseInt(date.substring(0, 4));
            if (year <= 0)
                return false;
            int month = Integer.parseInt(date.substring(4, 6));
            if (month <= 0 || month > 12)
                return false;
            int day = Integer.parseInt(date.substring(6, 8));
            if (day <= 0 || day > DAYS[month])
                return false;
            if (month == 2 && day == 29 && !isGregorianLeapYear(year)) {
                return false;
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * added by xulei 2017.01.13
     * @param year
     * @return
     */
    public static final boolean isGregorianLeapYear(int year) {
        return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
    }

    /**
     * 对日期进行转换
     *
     * @param srcFormat
     *            源数据的日期格式
     * @param targetFormat
     *            目标数据的日期格式
     * @param dateStr
     *            Added by xulei 2010.12.31
     * @return
     * @throws ParseException
     * @throws Exception
     */
    public static String dateFormat(String srcFormat, String targetFormat, String dateStr) throws ParseException{
        SimpleDateFormat sdf = new SimpleDateFormat(srcFormat);
        SimpleDateFormat sdf2 = new SimpleDateFormat(targetFormat);
        Date date = sdf.parse(dateStr);
        return sdf2.format(date);
    }

    /**
     * 对日期进行转换,去-补0到14位
     *
     *
     * added by xulei 2016.12.27
     * @param date
     *            日期格式 例：2008-08-08
     * @return
     */
    public static String dateFormat(String date){
        if(date != null && !"".equals(date)){
            String temp = date.replaceAll("-", "");
            if(temp.length() < 14){
                int j = 14 - temp.length();
                for(int i = 0; i < j; i++){
                    temp = temp + "0";
                }
            }
            return temp;
        }
        return date;
    }

    /**
     * 对日期进行转换,去-补235959到14位
     *
     *
     * added by xulei 2016.12.27
     * @param date
     *            日期格式 例：2008-08-08
     * @return
     */
    public static String dateFormatEnd(String date){
        if(date != null && !"".equals(date)){
            String temp = date.replaceAll("-", "");
            if(temp.length() == 8){
                temp = temp + "235959";
            }
            return temp;
        }
        return date;
    }

    /**
     * 剪裁图片为适应手机显示的大小，重新绘制后，转为新的base64字符串
     *
     * @param imageStr
     * @return
     * @throws Exception
     *             Added by xulei 2010.10.14
     */
    public static String reGraphicImage(String imageStr, int widthSize) throws Exception{
        Image image = null;
        BufferedImage bm = null;

        if(imageStr != null && imageStr.length() > 0){
            byte[] imageBytes = Utils.decodeBase64Tobyte(imageStr);
            ByteArrayInputStream imageBis = new ByteArrayInputStream(imageBytes);
            image = ImageIO.read(imageBis);
        }

        if(image != null){
            int oldwidth = image.getWidth(null);
            int oldheight = image.getHeight(null);
            int width = widthSize;
            logger.info("照片原始大小:" + oldwidth + ", 客户端需要的大小:" + widthSize);
            if(oldwidth < widthSize)
                width = oldwidth;
            int height = width * oldheight / oldwidth;
            bm = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_555_RGB);
            bm.getGraphics().drawImage(image, 0, 0, width, height, null);

            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ImageIO.write(bm, "PNG", bos);

            byte[] imageArrNew = bos.toByteArray();
            return Utils.byteArrayEncodeBase64(imageArrNew);
        }
        return null;
    }

    /**
     * added by xulei 2016.12.27
     * @param os
     */
    public static void safeClose(OutputStream os){
        try{
            if(os != null)
                os.close();
        }catch(Exception e){
            logger.error(e);
        }
    }

    /**
     * added by xulei 2016.12.27
     * @param in
     */
    public static void safeClose(InputStream in){
        try{
            if(in != null)
                in.close();
        }catch(Exception e){
            logger.error(e);
        }
    }

    /**
     * added by xulei 2016.12.27
     * @param zf
     */
    public static void safeClose(ZipFile zf){
        try{
            if(zf != null)
                zf.close();
        }catch(Exception e){
            logger.error(e);
        }
    }

    /**
     * 转码BASE64
     *
     * @param s
     * @return
     * @throws Exception
     * added by xulei 2016.12.27
     */
    public static String encodeBase64(String s) throws Exception{
        if(s != null){
            BASE64Encoder encoder = new BASE64Encoder();
            String str = encoder.encode(s.getBytes());
            return str;
        }
        return null;
    }

    /**
     * 将字节数组转码为BASE64
     *
     * @param arr
     * @return
     * @throws Exception
     * added by xulei 2016.12.27
     */
    public static String byteArrayEncodeBase64(byte[] arr) throws Exception{
        if(arr != null && arr.length > 0){
            BASE64Encoder encoder = new BASE64Encoder();
            String str = encoder.encode(arr);
            return str;
        }
        return null;
    }

    /**
     * 解码BASE64
     *
     * @param s
     * @return
     * @throws Exception
     * added by xulei 2016.12.27
     */
    public static String decodeBase64(String s) throws Exception{
        if(s != null){
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bs = decoder.decodeBuffer(s);
            return new String(bs);
        }
        return null;
    }

    /**
     * added by xulei 2016.12.27
     * @param s
     * @return
     * @throws Exception
     */
    public static byte[] decodeBase64Tobyte(String s) throws Exception{
        if(s != null){
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] bs = decoder.decodeBuffer(s);
            return bs;
        }
        return null;
    }


    /**
     * 获得文件MD5校验码
     *
     * @param path
     * @return
     * added by xulei 2016.12.27
     */
    public static String getFileMD5(String path){
        String md5Str = null;
        FileInputStream fis = null;
        ByteArrayOutputStream out = null;
        try{
            File f = new File(path);
            if(f.exists()){
                fis = new FileInputStream(f);
                out = new ByteArrayOutputStream();
                int length = 8192;
                byte[] datas = new byte[length];
                while((length = fis.read(datas, 0, length)) != -1){
                    out.write(datas, 0, length);
                }
                MessageDigest md = MessageDigest.getInstance("MD5");
                byte[] bs = md.digest(out.toByteArray());
                int i;
                StringBuffer buf = new StringBuffer("");
                for(int offset = 0; offset < bs.length; offset++){
                    i = bs[offset];
                    if(i < 0)
                        i += 256;
                    if(i < 16)
                        buf.append("0");
                    buf.append(Integer.toHexString(i));
                }
                md5Str = buf.toString().toUpperCase();
            }
        }catch(Exception e){
            e.printStackTrace();
        }finally{
            safeClose(fis);
            safeClose(out);
        }
        return md5Str;
    }

    /**
     * 获得字符串的MD5码
     *
     * @param str
     * @return
     * added by xulei 2016.12.27
     */
    public static String getStringMd5(String str){
        String md5Str = null;
        try{
            MessageDigest md = MessageDigest.getInstance("MD5");
            byte[] bs = md.digest(str.getBytes());
            int i;
            StringBuffer buf = new StringBuffer("");
            for(int offset = 0; offset < bs.length; offset++){
                i = bs[offset];
                if(i < 0)
                    i += 256;
                if(i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            md5Str = buf.toString().toUpperCase();
        }catch(Exception e){
            e.printStackTrace();
        }
        return md5Str;
    }

    /**
     * 对字符串进行MD5加密
     *
     * @param str
     * @return
     * @throws Exception
     * added by xulei 2016.12.27
     */
    public static String encodeMD5(String str) throws Exception{
        if(isEmpty(str)){
            return str;
        }

        try{
            MessageDigest mad5 = MessageDigest.getInstance("MD5");
            char[] charArray = str.toCharArray();
            byte[] byteArray = new byte[charArray.length];
            for(int i = 0; i < charArray.length; i++)
                byteArray[i] = (byte)charArray[i];
            byte[] md5Bytes = mad5.digest(byteArray);
            StringBuffer hexValue = new StringBuffer();
            for(int i = 0; i < md5Bytes.length; i++){
                int val = ((int)md5Bytes[i]) & 0xff;
                // if (val < 16)
                // hexValue.append("0");
                hexValue.append(Integer.toHexString(val));
            }
            return hexValue.toString();
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * 对字符串进行MD5加密
     *
     * @param str
     *            加密字符
     * @param add16
     *            是否补充到16位
     * @return
     * @throws Exception
     * added by xulei 2016.12.27
     */
    public static String encodeMD5(String str, boolean add16) throws Exception{
        try{
            MessageDigest mad5 = MessageDigest.getInstance("MD5");
            char[] charArray = str.toCharArray();
            byte[] byteArray = new byte[charArray.length];
            for(int i = 0; i < charArray.length; i++)
                byteArray[i] = (byte)charArray[i];
            byte[] md5Bytes = mad5.digest(byteArray);
            StringBuffer hexValue = new StringBuffer();
            for(int i = 0; i < md5Bytes.length; i++){
                int val = ((int)md5Bytes[i]) & 0xff;
                if(val < 16 && add16)
                    hexValue.append("0");
                hexValue.append(Integer.toHexString(val));
            }
            return hexValue.toString();
        }catch(Exception e){
            throw e;
        }
    }

    /**
     * 如果字符串为null返回空字符串，否则返回原字符串
     *
     * @param str
     * added by xulei 2016.12.27
     */
    public static String convertNullToEmpty(String str){
        if(str == null)
            return "";
        return str;
    }

    /**
     * 判断该字符串是否由数字组成
     *
     * @param str
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isNumber(String str){
        return str.matches("^\\-?[0-9]+(\\.?[0-9]+)?$");
    }

    /**
     * 通过本地文件完整路径获得文件名称
     *
     * @param fullFilePath
     * @return
     * added by xulei 2016.12.27
     */
    public static String getFileName(String fullFilePath){
        return fullFilePath.substring(fullFilePath.lastIndexOf("\\") + 1, fullFilePath.length());
    }

    /**
     * 判断字符串是否为整数
     *
     * @param str
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isInteger(String str){
        if(str == null || "".equals(str))
            return false;
        return java.util.regex.Pattern.matches("^[-+0-9]*$", str.trim());
    }

    /**
     * 判断是否为小数
     *
     * @param str
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isFloat(String str){
        if(str == null || "".equals(str))
            return false;
        // + - digits and point is allowed
        return java.util.regex.Pattern.matches("^[-+0-9.]*$", str.trim());
    }

    /**
     * 判断是否是英文字符串
     *
     * @param str
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isEnglishChar(String str){
        return java.util.regex.Pattern.matches("^[[a-z]|[A-Z]]*$", str.trim());
    }

    /**
     * 产生一个指定位数的随机码(随机码由数字或大小写字母构成)
     * added by xulei 2016.12.27
     */
    public static String createRandomCode(int randomCodeLen){
        final String str = "0123456789";
        final int maxNum = str.length();
        StringBuffer randomCode = new StringBuffer("");
        Random r = new Random();
        int count = 0;
        int ranDomNum = 0;
        while(count < randomCodeLen){
            // 生成随机数，取绝对值，防止生成负数，
            ranDomNum = Math.abs(r.nextInt(maxNum)); // 生成的数最大为maxNum-1, 最小为0
            randomCode.append(str.charAt(ranDomNum));
            count++;
        }

        return randomCode.toString();
    }

    /**
     * 格式化数字为0.00格式
     *
     * @param num
     * @return
     * added by xulei 2016.12.27
     */
    public static String formatNum(double num){
        return formatNum(num, "0.00");
    }

    /**
     * 格式化数字为指定格式
     *
     * @param num
     * @param formatStr
     * @return
     * added by xulei 2016.12.27
     */
    public static String formatNum(double num, String formatStr){
        DecimalFormat df = new DecimalFormat(formatStr);
        return df.format(num);
    }

    /**
     * 将参数各个元素用下划线连接起来
     *
     * @param items
     * @return
     *
     * @author xulei
     * @date 2013-8-2 下午5:40:04
     */
    public static String linkWithUnderline(Object... items){
        return linkWithSymbol("_", items);
    }

    /**
     * 将参数各个元素用竖线连接起来
     *
     * @param items
     * @return
     *
     * @author xulei
     * @date 2013-8-2 下午5:40:04
     */
    public static String linkWithVerticalLine(Object... items){
        return linkWithSymbol("|", items);
    }

    /**
     * 将参数各个元素用指定的符号连接起来
     *
     * @param symbol
     * @param items
     * @return
     *
     * @author xulei
     * @date 2013-8-2 下午5:40:04
     */
    public static String linkWithSymbol(String symbol, Object... items){
        if(items == null || items.length == 0){
            return null;
        }

        if(items.length == 1){
            return items[0].toString();
        }

        StringBuilder sb = new StringBuilder();
        for(Object s : items){
            sb.append(symbol).append(s);
        }

        return sb.toString().substring(1);
    }

    /**
     * added by xulei 2016.12.27
     * @param str
     * @return
     */
    public static List<String> spiltByUnderline(String str){
        return spiltBySymbol("_", str);
    }

    /**
     * added by xulei 2016.12.27
     * @param str
     * @return
     */
    public static List<String> spiltByVerticalLine(String str){
        return spiltBySymbol("\\|", str);
    }

    /**
     * added by xulei 2016.12.27
     * @param symbol
     * @param str
     * @return
     */
    public static List<String> spiltBySymbol(String symbol, String str){
        if(isEmpty(str)){
            return null;
        }

        String[] arr = str.split(symbol);
        List<String> list = new ArrayList<String>(arr.length);
        for(String item : arr){
            list.add(item);
        }
        return list;
    }

    /**
     * 格式化double类型的小数个数
     *
     * @param num
     *            格式化数值
     * @param scale
     *            保留小数位数
     * @return
     * added by xulei 2016.12.27
     */
    public static double scaleDouble(double num, int scale){
        int i = 1;
        for(int j = 0; j < scale; j++){
            i *= 10;
        }
        return (double)Math.round(num * i) / i;
    }

    /**
     * 产生唯一的文件名
     *
     * @param filename
     * @return
     * added by xulei 2016.12.27
     */
    public static synchronized String generateFileName(String filename){
        int position = filename.lastIndexOf(".");
        String ext = filename.substring(position);
        return System.nanoTime() + ext;
    }

    /**
     * Integer类型的对象值是否大于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isIntGT(Integer val, int comparedVal) {
        return val != null && val > comparedVal;
    }

    /**
     * Integer类型的对象值是否小于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isIntLT(Integer val, int comparedVal) {
        return val != null && val < comparedVal;
    }

    /**
     * Integer类型的对象是否等于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isIntEq(Integer val, int comparedVal) {
        return val != null && val == comparedVal;
    }

    /**
     * Short类型的对象值是否大于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isShortGT(Short val, int comparedVal) {
        return val != null && val > comparedVal;
    }

    /**
     * Short类型的对象值是否小于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isShortLT(Short val, int comparedVal) {
        return val != null && val < comparedVal;
    }

    /**
     * Short类型的对象是否等于指定值
     * @param val
     * @param comparedVal
     * @return
     * added by xulei 2016.12.27
     */
    public static boolean isShortEq(Short val, int comparedVal) {
        return val != null && val == comparedVal;
    }
    
   /** 
    * 获取当前日期在当年的第几天，在当月中的第几天
    * @param time ,flag
    * added by ywhu 2016.12.29
    */
    
    public static int getDaysCount(Date time , String flag){
        int count =0;
        if(!isEmpty(time)&&!isEmpty(flag)){
          Calendar ca=Calendar.getInstance();  
          ca.setTime(time); 
          if(flag.equals("year")){
              count = ca.get(Calendar.DAY_OF_YEAR);
          }else if(flag.equals("month")){
              count = ca.get(Calendar.DAY_OF_MONTH); 
          }
        }
        return count;
    }
    
    /** 
     * 获取当月第1天和最后一天，上月中的第1天和最后一天,本年的第一天和最后一天
     * @param flag
     * added by ywhu 2016.12.29
     */
    
    public static Date[] getDayFirstAndLast( String flag){
        Date[] firstAndLat = new Date[2];
        Date first = null;
        Date last = null;
        Calendar c = Calendar.getInstance();    
        if(!isEmpty(flag)){
           if(flag.equals("currentMonth")){
             //获取当月第一天：
             c.add(Calendar.MONTH, 0);
             c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天 
             first = c.getTime();
             //获取当月最后一天
             c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));  
             last = c.getTime();
             c.clear();
           }else if(flag.equals("lastMonth")){
             //获取前月的第一天
             c.add(Calendar.MONTH, -1);
             c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天 
             first = c.getTime();
             
             //获取前月的最后一天
             c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH)); 
             last = c.getTime();
             c.clear();
           }else if(flag.equals("currentYear")){
             
             //获取当年最后一天
             Calendar calendar = Calendar.getInstance();
             int currentYear =  calendar.get(Calendar.YEAR);
             calendar.clear();
             calendar.set(Calendar.YEAR, currentYear);  
             calendar.roll(Calendar.DAY_OF_YEAR, -1);  
             last = calendar.getTime();
             
             //获取当年第一天
             calendar.clear();
             calendar.set(Calendar.YEAR, currentYear);
             first = calendar.getTime();
           }
        }
        if(!isEmpty(first)&&!isEmpty(last)){
          firstAndLat[0] = first;
          firstAndLat[1] = last;
        }
        return firstAndLat;
    }
    
    /**
     * 获取某月的第一天个最后一天的日期
     */
    public static List<Date> getFirstAndLastDayOfMonth(Date time){
        List<Date> dates = new ArrayList<>();
        Date first = null;
        Date last = null;
        if(time!=null){
          Calendar c = Calendar.getInstance();
          c.setTime(time);
          int year = c.get(Calendar.YEAR);
          int month = c.get(Calendar.MONTH)+1;
          Calendar cal = Calendar.getInstance();
          // 不加下面2行,就是取当前时间前一个月的第一天及最后一天
          cal.set(Calendar.YEAR,year);
          cal.set(Calendar.MONTH, month);
          cal.set(Calendar.DAY_OF_MONTH, 1);
          cal.add(Calendar.DAY_OF_MONTH, -1);
          last = cal.getTime();
  
          cal.set(Calendar.DAY_OF_MONTH, 1);
          first = cal.getTime();
        }
        dates.add(first);
        dates.add(last);
        
        return dates;
    }
    
    
    /** 
    * 获得指定日期的前一天 
    * @param specifiedDay 
    * @return 
    * @throws Exception 
    */ 
    public static String getSpecifiedDayBefore(String specifiedDay){ 
        Calendar c = Calendar.getInstance(); 
        Date date=null; 
        try { 
          date = new SimpleDateFormat("yyyy-MM-dd").parse(specifiedDay); 
        } catch (ParseException e) { 
        e.printStackTrace(); 
        } 
        c.setTime(date); 
        int day=c.get(Calendar.DATE); 
        c.set(Calendar.DATE,day); 
    
        String dayBefore=formatDate(c.getTime()); 
        return dayBefore; 
    } 
    /** 
    * 获得指定日期的后一天 
    * @param specifiedDay 
    * @return 
    */ 
    public static String getSpecifiedDayAfter(String specifiedDay){ 
        Calendar c = Calendar.getInstance(); 
        Date date=null; 
        try { 
          date = new SimpleDateFormat("yyyy-MM-dd").parse(specifiedDay); 
        } catch (ParseException e) { 
          e.printStackTrace(); 
        } 
        c.setTime(date); 
        int day=c.get(Calendar.DATE); 
        c.set(Calendar.DATE,day+1); 
    
        String dayAfter=formatDate(c.getTime()); 
        return dayAfter; 
    }
    
    /**
     * 拆分字符串为
     */
    public static String[] splitString(String str,String chart){
      if(str.indexOf(chart)==-1){
          String[] temp = {str};
          return temp;
      }else{
          String[] temp = str.split(chart);
          return temp;
      }
    }
    
    //求两个数组是否有交集   
     public static boolean intersect(Long[] arr1, Long[] arr2) {   
         Map<Long, Boolean> map = new HashMap<Long, Boolean>();   
         LinkedList<Long> list = new LinkedList<Long>();   
         for (long str : arr1) {   
            if (!map.containsKey(str)) {   
                 map.put(str, Boolean.FALSE);   
             }   
        }   
        for (long str : arr2) {   
             if (map.containsKey(str)) {   
                 map.put(str, Boolean.TRUE);   
             }   
         }   
   
         for (Entry<Long, Boolean> e : map.entrySet()) {   
             if (e.getValue().equals(Boolean.TRUE)) {   
                 list.add(e.getKey());   
             }   
         }   
   
         Long[] result = {};   
         if(list.toArray(result).length==0){
             return false;
         }else{
           return true;
         }   
     } 
     
     /** 
      * 判断是否是周末 
      * @return 
      */  
     public static boolean isWeekend(Calendar cal){  
         int week=cal.get(Calendar.DAY_OF_WEEK)-1;  
         if(week ==6 || week==0){//0代表周日，6代表周六  
             return true;  
         }  
         return false;  
     }  
}
